<?php

/**
 * 聊天室
 */

class Chat
{
    const HOST = '0.0.0.0';//ip地址 0.0.0.0代表接受所有ip的访问
    const PART = 8125;//端口号
    private $server = null;//单例存放websocket_server对象
    private $redis;

    public function __construct()
    {
        $this->redis = new Redis();
        $this->redis->connect("127.0.0.1", 6379);
        $this->redis->flushAll();//删除数据的所有key

        //实例化swoole_websocket_server并存储在我们Chat类中的属性上，达到单例的设计
//        $this->server = new swoole_websocket_server(self::HOST, self::PART);
        $this->server = new swoole_websocket_server(self::HOST, self::PART, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
        //file_put_contents('sslcert.txt',dirname(__FILE__));
        $this->server->set([
            'ssl_cert_file' => dirname(__FILE__).'/ssl/key2.pem',
            'ssl_key_file' => dirname(__FILE__).'/ssl/key1.key',
            'worker_num' => 4,
            'task_worker_num' => 4,
            'heartbeat_check_interval' => 60,
            'heartbeat_idle_time' => 120,
        ]);
        $this->server->on('start', [$this, 'onStart']);
        //监听连接事件
        $this->server->on('open', [$this, 'onOpen']);
        //监听接收消息事件
        $this->server->on('message', [$this, 'onMessage']);
        //监听关闭事件
        $this->server->on('close', [$this, 'onClose']);
        $this->server->on("task", [$this, 'onTask']);
        $this->server->on("finish", [$this, 'onFinish']);
        //开启服务
        $this->server->start();

        //不知道心跳定时起不起作用

//        $client = new swoole_client(SWOOLE_SOCK_TCP | SWOOLE_ASYNC);
//        //file_put_contents('1heartbeat1111.txt', json_encode($client));
//        Swoole\Timer::tick(3000, function () use ($client) {
//            $data = "heartbeat";
//            //file_put_contents('2heartbeat.txt', '心跳');
//            $client->send($data);
//        });
    }

    public function onStart($serv)
    {
        swoole_set_process_name("live_master");
    }

    /**
     * 连接成功回调函数
     * @param $server
     * @param $request
     */
    public function onOpen($server, $request)
    {
        $connect_status = $this->redis->ping();
        if($connect_status != "+PONG")
        {
            $this->redis = new Redis();
            $this->redis->connect('127.0.0.1', 6379);
        }
        $chapterid = $request->get['sonid'];
        $dataJson = $this->redis->get('livemember' . $chapterid);
        if (empty($dataJson)) {
            $data[] = $request->fd;
            $this->redis->set('livemember' . $chapterid, json_encode($data));
        } else {
            $data = json_decode($dataJson, true);
            if (!in_array($request->fd, $data)) {
                array_push($data, $request->fd);
                $this->redis->set('livemember' . $chapterid, json_encode($data));
            }
        }
        //返回实时人数
        $rangnum = rand(200, 250);
        $totalnum = count($data) + $rangnum;
        $rdata = ['totalnum' => $totalnum];
        $datas = [
            'fd' => $data,
            'message' => json_encode($rdata),
        ];
        $server->task($datas);
    }

    /**
     * 接收到信息的回调函数
     * @param $server
     * @param $frame
     */
    public function onMessage($server, $frame)
    {
        $da = json_decode($frame->data, true);
        $chapterid = $da['sonid'];
        $fdlist = $this->redis->get('livemember' . $chapterid);
        $data = [
            'task' => 1,
            'fd' => json_decode($fdlist, true),
            'message' => $frame->data,
        ];
        $server->task($data);
    }

    /**
     * @param $serv
     * @param $taskId
     * @param $workerId
     * @param $data
     */
    public function onTask($serv, $taskId, $workerId, $data)
    {
        // 分发 task 任务机制，让不同的任务 走不同的逻辑
        if ($data['fd']) {
            foreach ($data['fd'] as $k => $v) {
                $connectInfo = $serv->connection_info($v);
                if ($connectInfo['websocket_status']) {
                    $serv->push($v, $data['message']);
                }
            }
            return 'OK'; // 告诉worker
        }
    }

    /**
     * @param $serv
     * @param $taskId
     * @param $data
     */
    public function onFinish($serv, $taskId, $data)
    {
        echo "taskId:{$taskId}\n";
        echo "finish-data-sucess:{$data}\n";
    }

    /**
     * 断开连接回调函数
     * @param $server
     * @param $fd
     */
    public function onClose($server, $fd)
    {
        $search = $this->redis->keys('livemember*');
        if ($search) {
            foreach ($search as $k => $v) {
                //该房间fd数组
                $fdlist = $this->redis->get($v);
                $fdlistData = json_decode($fdlist, true);
                if (is_array($fdlistData)) {
                    if (in_array($fd, $fdlistData)) {
                        unset($fdlistData[array_search($fd, $fdlistData)]);
                    }
                }
                $this->redis->set($v, json_encode($fdlistData));
            }
        }
    }
}

$obj = new Chat();